package com.example.lasttrain.common;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.provider.BaseColumns;

/** データベースへの情報登録・読み出しを行うクラス */
public class DatabaseUtils {

	/***
	 * IDに対応した終電情報を1件取得、存在しない場合はnullを返却
	 * （リスト項目を選択した際に使用するイメージです。）
	 * @param context
	 * @param id
	 * @param trainEntry（戻り値用）
	 * @return　trainEntry(各項目をセットしたTrainEntryクラスのインスタンス)
	 */
	public static TrainEntry getContents(Context context, int id) {
		DatabaseHelper helper = null;
		SQLiteDatabase db = null;
		Cursor cur = null;
		TrainEntry trainEntry = new TrainEntry();
		
		try {
			// Helperクラスの生成
			helper = new DatabaseHelper(context);
			// 読込み用SQLiteDatabaseを生成
			db = helper.getWritableDatabase();

			// projection(select句)の作成
			String[] projection =  
				new String[] { 
					BaseColumns._ID,
					Defines.FIELD_PATTERN_NAME,
					Defines.FIELD_BOARDING_STA,
					Defines.FIELD_DROPPING_STA,
					Defines.FIELD_LAST_TIME,
					Defines.FIELD_ALARM_TIME,
					Defines.FIELD_ALARM_FLG
				};
			
			// table(from句)のセット
			String table = Defines.TABLE_NAME_L;
			
			// selection(where句)の作成
			String selection = BaseColumns._ID + " = ?";
			
			// selectionArgs(selectionの？に埋め込む文字列[])の作成
			String stringID = Integer.toString(id);
			String[] selectionArgs = new String[] { stringID };
			
			// groupByの作成
			String groupBy = null; 
			// havingの作成
			String having = null; 
			// orderByの作成
			String orderBy = null; 

			// 検索処理の実行(デバッグ)
//			cur = db.query(table, projection, null, null, groupBy, having, orderBy, "1");
			
			// 検索処理の実行
			cur = db.query(table, projection, selection, selectionArgs, groupBy, having, orderBy, "1");
			
			//　検索がヒットしたら、先頭の1件の終電情報の内容をセットして返す
			if (cur != null && cur.moveToFirst()) {
				trainEntry.setName(cur.getString(cur.getColumnIndex(Defines.FIELD_PATTERN_NAME)));
				trainEntry.setDbId(id);
				trainEntry.setStartStation(cur.getString(cur.getColumnIndex(Defines.FIELD_BOARDING_STA)));
				trainEntry.setEndStation(cur.getString(cur.getColumnIndex(Defines.FIELD_DROPPING_STA)));
				trainEntry.setAlarmtime(cur.getInt(cur.getColumnIndex(Defines.FIELD_ALARM_TIME)));
				trainEntry.setAlarmFlg(cur.getInt(cur.getColumnIndex(Defines.FIELD_ALARM_FLG)));
				// 終電時刻だけTimeData型に加工してセット
				String strLastTime = cur.getString(cur.getColumnIndex(Defines.FIELD_LAST_TIME));
				TimeData timLastTime = convertStringToTimeDate(strLastTime);
				trainEntry.setTrainTime(timLastTime);
				
				return trainEntry;
		
			} else {
				return null;
			}
		} finally {
			// 終了処理
			if (cur != null) {
				cur.close();
			}
			if (db != null) {
				db.close();
			}
			if (helper != null) {
				helper.close();
			}
		}
	}
	
	/***
	 * 終電情報の一覧を取得するメソッド
	 * （一覧表示画面で使用するイメージです。）
	 * @param context
	 * @return　TrainEntry（終電情報の一覧）
	 */
	public static ArrayList<TrainEntry> getTitleList(Context context){
		DatabaseHelper helper = null;
		SQLiteDatabase db = null;
		Cursor cur = null;
		ArrayList<TrainEntry> trainEntryList = new ArrayList<TrainEntry>();
		
		try {
			// Helperクラスの生成
			helper = new DatabaseHelper(context);
			// 読込み用SQLiteDatabaseを生成
			db = helper.getWritableDatabase();

			// projection(select句)の作成
			String[] projection =  
				new String[] {
					BaseColumns._ID,
					Defines.FIELD_PATTERN_NAME,
					Defines.FIELD_BOARDING_STA,
					Defines.FIELD_DROPPING_STA,
					Defines.FIELD_LAST_TIME,
					Defines.FIELD_ALARM_TIME,
					Defines.FIELD_ALARM_FLG
				};
			
			// table(from句)のセット
			String table = Defines.TABLE_NAME_L;
			
			// selection(where句)の作成
			String selection = Defines.FIELD_DELETE_FLG + " = 0";
			
			// selectionArgs(selectionの？に埋め込む文字列[])の作成
			String[] selectionArgs = null;
			// groupByの作成
			String groupBy = null; 
			// havingの作成
			String having = null; 
			// orderByの作成
			String orderBy = null; 
			
			// 検索処理の実行
			cur = db.query(table, projection, selection, selectionArgs, groupBy, having, orderBy);
			
			// 検索がヒットしたら終電情報のリストを作成
			if (cur != null) {
				// 結果がnullでなかったら、ループしながらtitleの値をセット
				boolean isEof = cur.moveToFirst();
				while(isEof){
					TrainEntry trainEntry = new TrainEntry();
					
					trainEntry.setName(cur.getString(cur.getColumnIndex(Defines.FIELD_PATTERN_NAME)));
					trainEntry.setDbId(cur.getInt(cur.getColumnIndex(BaseColumns._ID)));
					trainEntry.setStartStation(cur.getString(cur.getColumnIndex(Defines.FIELD_BOARDING_STA)));
					trainEntry.setEndStation(cur.getString(cur.getColumnIndex(Defines.FIELD_DROPPING_STA)));
					trainEntry.setAlarmtime(cur.getInt(cur.getColumnIndex(Defines.FIELD_ALARM_TIME)));
					trainEntry.setAlarmFlg(cur.getInt(cur.getColumnIndex(Defines.FIELD_ALARM_FLG)));
					// 終電時刻だけTimeData型に加工してセット
					String strLastTime = cur.getString(cur.getColumnIndex(Defines.FIELD_LAST_TIME));
					TimeData timLastTime = convertStringToTimeDate(strLastTime);
					trainEntry.setTrainTime(timLastTime);;
					
					// 配列にオブジェクトを格納
					trainEntryList.add(trainEntry);
					isEof = cur.moveToNext();
				}
				
				return trainEntryList;
				
			} else {
				// 結果が0件ならnullを返す
				return null;
			}
		} finally {
			// 終了処理
			if (cur != null) {
				cur.close();
			}
			if (db != null) {
				db.close();
			}
			if (helper != null) {
				helper.close();
			}
		}
	}
	
	/***
	 * IDに該当する削除情報を更新
	 * （UPDATEメソッド）
	 * @param context 
	 * @param int id (削除したいレコードのid)
	 * @return boolean (true：成功、false：失敗)
	 */
	public static boolean deleteContents(Context context, int id) {
		DatabaseHelper helper = null;
		SQLiteDatabase db = null;
		try {
			// Helperクラスの生成
			helper = new DatabaseHelper(context);
			// 書込み用SQLiteDatabaseを生成
			db = helper.getWritableDatabase();
			
			// tableのセット
			String table = Defines.TABLE_NAME_L;
			
			// selection(where句)の作成
			String selection = "_ID = ?";
			
			// selectionArgs(selectionの？に埋め込む文字列[])の作成
			String stringID = Integer.toString(id);
			String[] selectionArgs = new String[] { stringID };
			
			// values：書き込み用のデータを作成
			ContentValues values = new ContentValues();
			values.put(Defines.FIELD_DELETE_FLG, 1);
			
			// IDをキーにアップデート処理の実行
			db.update( table, values, selection, selectionArgs);
			
			return true;
			
		} finally {
			// 終了処理
			if (db != null) {
				db.close();
			}
			if (helper != null) {
				helper.close();
			}
		}
	}
	
	/***
	 * IDに該当するアラームフラグを更新
	 * （UPDATEメソッド）
	 * @param context 
	 * @param int id (レコードのid)
	 * @param int alarm (アラームのON、OFF)
	 * @return boolean (true：成功、false：失敗)
	 */
	public static boolean alarmContents(Context context, int id, int alarm) {
		DatabaseHelper helper = null;
		SQLiteDatabase db = null;
		try {
			// Helperクラスの生成
			helper = new DatabaseHelper(context);
			// 書込み用SQLiteDatabaseを生成
			db = helper.getWritableDatabase();
			
			// tableのセット
			String table = Defines.TABLE_NAME_L;
			
			// selection(where句)の作成
			String selection = "_ID = ?";
			
			// selectionArgs(selectionの？に埋め込む文字列[])の作成
			String stringID = Integer.toString(id);
			String[] selectionArgs = new String[] { stringID };
			
			// values：書き込み用のデータを作成
			ContentValues values = new ContentValues();
			values.put(Defines.FIELD_ALARM_FLG, alarm);
			
			// IDをキーにアップデート処理の実行
			db.update( table, values, selection, selectionArgs);
			
			return true;
			
		} finally {
			// 終了処理
			if (db != null) {
				db.close();
			}
			if (helper != null) {
				helper.close();
			}
		}
	}
	
	
	
	/***
	 * データベースの更新処理。データがあればinsert、なければUpdate
	 * （編集画面にて保存ボタンを押した時に使うイメージです。）
	 * @param context 
	 * @param trainEntry (登録情報を格納したTrainEntryクラスのインスタンス)
	 * @return true/false (成功したらtrue/失敗でfalse)
	 */
	public static boolean upRecord(Context context, TrainEntry trainEntry) {
		
		// 必須項目のチェック
		if( trainEntry.getDbId() < -1 ){
			return false;
		}
		
		// 年の為IDをキーにデータベースを検索
		TrainEntry idCheck = getContents( context, trainEntry.getDbId());
        // 既にデータが登録済みなら更新。そうでなければ登録。
        if (idCheck != null) {
	        return DatabaseUtils.updateContents( context, trainEntry);
        } else {
        	return DatabaseUtils.createContents( context, trainEntry);
        }
	}
	
	/***
	 * IDに該当する終電情報を更新
	 * （UPDATEメソッド）
	 * @param context 
	 * @param TrainEntry trainEntry (登録内容のオブジェクト)
	 * @return boolean (true：成功、false：失敗)
	 */
	public static boolean updateContents(Context context, TrainEntry trainEntry) {
		DatabaseHelper helper = null;
		SQLiteDatabase db = null;
		try {
			// Helperクラスの生成
			helper = new DatabaseHelper(context);
			// 書込み用SQLiteDatabaseを生成
			db = helper.getWritableDatabase();
			
			// tableのセット
			String table = Defines.TABLE_NAME_L;
			
			// selection(where句)の作成
			String selection = BaseColumns._ID + " = ?";
			
			// selectionArgs(selectionの？に埋め込む文字列[])の作成
			String stringID = Integer.toString(trainEntry.getDbId());
			String[] selectionArgs = new String[] { stringID };
			
			// values：書き込み用のデータを作成
			ContentValues values = new ContentValues();
			values = makeValues(values, trainEntry, Defines.UPDATE);
			
			// IDをキーにアップデート処理の実行
			db.update( table, values, selection, selectionArgs);
			
			return true;
			
		} finally {
			// 終了処理
			if (db != null) {
				db.close();
			}
			if (helper != null) {
				helper.close();
			}
		}
	}

	/***
	 * 新しくレコードを登録
	 * （INSERTメソッド）
	 * @param context 
	 * @param TrainEntry trainEntry (登録内容のオブジェクト)
	 * @return boolean (true：成功、false：失敗)
	 */
	public static boolean createContents(Context context, TrainEntry trainEntry) {
		DatabaseHelper helper = null;
		SQLiteDatabase db = null;
		try {
			// Helperクラスの生成
			helper = new DatabaseHelper(context);
			// 書込み用SQLiteDatabaseを生成
			db = helper.getWritableDatabase();
			
			// tableのセット
			String table = Defines.TABLE_NAME_L;

			// values:書き込み用のデータを作成
			ContentValues values = new ContentValues();
			values = makeValues(values, trainEntry, Defines.REGISTER);

			// インサート処理の実行
			db.insert(table, null, values);
			
			return true;
			
		} finally {
			// 終了処理
			if (db != null) {
				db.close();
			}
			if (helper != null) {
				helper.close();
			}
		}
	}
	
	/***
	 * DBに登録・更新したいContentValuesを作成する処理
	 * @param ContentValues values 値格納用のオブジェクト
	 * @param int type 登録ならRegister、更新ならUpdate
	 * @return values 値格納後のオブジェクト
	 */
	public static ContentValues makeValues(ContentValues values, TrainEntry trainEntry, int type){
		
		// 登録時のContentValuesを作成
		if(type == Defines.REGISTER ){
			// 必須項目のチェック
			if(	trainEntry.getName() == null ||
				trainEntry.getStartStation() == null ||
				trainEntry.getEndStation() == null ||
				trainEntry.getTrainTime() == null ||
				trainEntry.getAlarmtime() < -1 ){
					return null;
			}
			
			// 登録内容をセットしていく
			values.put(Defines.FIELD_PATTERN_NAME, trainEntry.getName());
			values.put(Defines.FIELD_BOARDING_STA, trainEntry.getStartStation());
			values.put(Defines.FIELD_DROPPING_STA, trainEntry.getEndStation());
			values.put(Defines.FIELD_ALARM_TIME, trainEntry.getAlarmtime());
			values.put(Defines.FIELD_LAST_TIME, convertTimeDateToString(trainEntry.getTrainTime()));
			//登録日時をセット
			values.put(Defines.FIELD_CREATE_DATE_L, getNowDate() );
			// 削除フラグをセット
			values.put(Defines.FIELD_DELETE_FLG, 0 );
			
		// 更新時のContentValuesを作成
		}else if(type == Defines.UPDATE){
			// 値を渡されている場合のみ更新情報にセットしていく
			values = new ContentValues();
			if( trainEntry.getName() != null){
				values.put(Defines.FIELD_PATTERN_NAME, trainEntry.getName());
			}
			if( trainEntry.getName() != null){
				values.put(Defines.FIELD_BOARDING_STA, trainEntry.getStartStation());
			}
			if( trainEntry.getName() != null){
				values.put(Defines.FIELD_DROPPING_STA, trainEntry.getEndStation());
			}
			if( trainEntry.getName() != null){
				values.put(Defines.FIELD_ALARM_TIME, trainEntry.getAlarmtime());
			}
			if( trainEntry.getName() != null){
				// 終電時刻はTimeData型からStringに加工してセット
				values.put(Defines.FIELD_LAST_TIME, convertTimeDateToString(trainEntry.getTrainTime()));
			}
			// 更新時刻をセット
			values.put(Defines.FIELD_UPDATE_DATE_L, getNowDate() );
		}else{
			return null;
		}
		
		return values;
	}
	
	/***
	 * 4桁のString型の時刻をTimeData型に変換する処理
	 * @param String strTime "HHMM"型の時間を表す文字列
	 * @return TimeData 変換後の時間
	 */
	public static TimeData convertStringToTimeDate(String strTime){
		// それぞれint型の時・分に変換
		int hour = Integer.parseInt(strTime.substring(0, 2));
		int minute = Integer.parseInt(strTime.substring(2, 4));

		// 時・分情報をもつTimeDataインスタンスを生成
		TimeData tdTime = new TimeData(hour, minute);
		
		return tdTime;
	}
	
	/***
	 * TimeData型の時刻を4桁のString型に変換する処理
	 * @param TimeData tdTime 時間情報
	 * @return strTime "HHMM"型の時間を表す文字列
	 */
	public static String convertTimeDateToString(TimeData tdTime){
		// それぞれString型の時・分に変換
		String stHour = Integer.toString(tdTime.getHour());
		String stMinute = Integer.toString(tdTime.getMinute());
		
		// 時・分情報を作成
        if(stHour.length()==1) stHour = "0" + stHour;
        if(stMinute.length()==1) stMinute = "0" + stMinute;
        String strTime = stHour + stMinute;
		
		return strTime;
	}
	
	/***
	 * 現在の時刻をlong型で返す処理
	 * @return long date
	 */
	public static long getNowDate(){
	    Calendar calendar = Calendar.getInstance();
	    Date mDate = calendar.getTime();
	    long date = mDate.getTime();
	    return date;
	}

	
}
